﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Threading;
using System.Windows.Threading;
using System.Diagnostics;

using Sprites;
using JavaSubstitutes;

namespace infiniteMarioDotNet
{
	public partial class MainPage : UserControl
	{
		MarioComponent mario;

		public MainPage()
		{
			InitializeComponent();
		}

		private void UserControl_Loaded(object sender, RoutedEventArgs e)
		{
			//StartMario();			  
			//PrepForBGRenderTest();
		}


        DispatcherTimer dt = new DispatcherTimer() { Interval = new TimeSpan(0,0,0,0,200) };
		private void StartMario()
		{
            dt.Tick += (sender, args) =>
                {
                    if (Art.FinishedInitializing)
                    {
                        dt.Stop();
                        mario.start(LayoutRoot);
                    }
                };

            GraphicsConfiguration gc = new GraphicsConfiguration(LayoutRoot);
			Sonar.SonarSoundEngine engine = new Sonar.SonarSoundEngine();
			Art.init(gc, engine);
			//Art.init(gc, null);Art.init(gc, null);
			mario = new MarioComponent(320, 240);
			LayoutRoot.Children.Add(mario);
                        
            dt.Start();
			//mario.start(LayoutRoot);
		}

		private void Button_Click(object sender, RoutedEventArgs e)
		{
			testAnimateMario();
		}

		private void testAnimateMario()
		{
			GraphicsConfiguration gc = new GraphicsConfiguration(LayoutRoot);
			Art.init(gc, null);

			LayoutRoot.Children.RemoveAllButType(typeof(MediaElement));

			Image img = new Image();
			LayoutRoot.Children.Add(img);
			WriteableBitmap bmp = new WriteableBitmap(32, 32);

			int i = 0;
			DispatcherTimer dt = new DispatcherTimer() { Interval = new TimeSpan(0, 0, 0, 0, 150) };
			dt.Tick += (senderDT, args) =>
			{
				bmp.Clear();

				bmp.Render(Art.fireMario[i, 0], null);
				bmp.Invalidate();
				img.Source = bmp;

				i++;
				if (i >= Art.fireMario.Length) i = 0;
			};

			dt.Start();

			//MessageBoy.Show("done");
		}


		private void testMoveMario()
		{
			GraphicsConfiguration gc = new GraphicsConfiguration(LayoutRoot);
			Art.init(gc, null);

			LayoutRoot.Children.RemoveAllButType(typeof(MediaElement));

			Image img = new Image();
			LayoutRoot.Children.Add(img);
			WriteableBitmap bmp = new WriteableBitmap(32, 32);

			bmp.Clear();
			bmp.Render(Art.fireMario[2, 0], null);


			int i = 0;
			DispatcherTimer dt = new DispatcherTimer() { Interval = new TimeSpan(0, 0, 0, 0, 500) };
			dt.Tick += (senderDT, args) =>
			{
				bmp.copyAndMoveArea(0, 0, 32, 32, 2, 2);
				bmp.Invalidate();
				img.Source = bmp;

				i++;
				if (i >= 15)
				{
					i = 0;
					MessageBox.Show("done");
				}
			};

			dt.Start();


		}

		private void Button_Click_1(object sender, RoutedEventArgs e)
		{
			testMoveMario();

		}

		private void Button_Click_2(object sender, RoutedEventArgs e)
		{
			GraphicsConfiguration gc = new GraphicsConfiguration(LayoutRoot);
			Sonar.SonarSoundEngine engine = new Sonar.SonarSoundEngine();
			Art.init(gc, engine);

			LayoutRoot.Children.RemoveAllButType(typeof(MediaElement));

			Image img = new Image();
			LayoutRoot.Children.Add(img);
			WriteableBitmap bmp = new WriteableBitmap(320, 240);

			bmp.Clear();
			//wbmp.Render(Art.fireMario[2, 0], null);

			LevelScene.renderBlackout(bmp, 0, 0, 16);
			bmp.Invalidate();
			img.Source = bmp;
		}

		private void Button_Click_3(object sender, RoutedEventArgs e)
		{
			StartMario();

		}

		private void Button_Click_4(object sender, RoutedEventArgs e)
		{
			GraphicsConfiguration gc = new GraphicsConfiguration(LayoutRoot);
			Art.init(gc, null);

			Dispatcher.BeginInvoke(() =>
				{
					LayoutRoot.Children.RemoveAllButType(typeof(MediaElement));

					Image img = new Image();
					LayoutRoot.Children.Add(img);
					WriteableBitmap bmp = new WriteableBitmap(8 * 32, 10 * 32); //32py tiles 8,10

					int i = 0;

					for (int y = 0; y < 10; y++)
						for (int x = 0; x < 8; x++)
						{
							//wbmp.Render(Art.bg[destX, destY], null);
							bmp.drawImage(Art.bg[x, y], x*32, y*32);
							bmp.Invalidate(); //after every  time?
						}

					bmp.Invalidate();
					img.Source = bmp;

				});
		}

		private void clickInitArt(object sender, RoutedEventArgs e)
		{
			GraphicsConfiguration gc = new GraphicsConfiguration(LayoutRoot);
			Art.init(gc, null);			
		}

        private void LayoutRoot_KeyDown(object sender, KeyEventArgs e)
        {
			if (mario == null)
			{
				//for testing the level scrolling
				if (e.Key == Key.Left)
					MoveRight();

				if (e.Key == Key.Right)
					MoveLeft();

				return;
			}

            mario.toggleKey(e.Key, true);
        }

        private void LayoutRoot_KeyUp(object sender, KeyEventArgs e)
        {
			if (mario == null) return;

            mario.toggleKey(e.Key, false);
        }

        private void LayoutRoot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
			if (mario == null) return;
            mario.ShowStartGameScene();
        }

		private void Button_Click_5(object sender, RoutedEventArgs e)
		{
			//test.Position = new TimeSpan();
			//test.Play();
		}

		private void test_MediaOpened(object sender, RoutedEventArgs e)
		{
			Debug.WriteLine("got sound");
		}

		private void test_MediaFailed(object sender, ExceptionRoutedEventArgs e)
		{
			MessageBox.Show("media failed");
		}

		private void btnFlip_Click(object sender, RoutedEventArgs e)
		{
			//WriteableBitmap bmp = new WriteableBitmap((int)imgTest.ActualWidth, (int)imgTest.ActualHeight);
			//drawImage(bmp, imgTest, 0, 0, null);

		}


		//test
		public  void drawImage(WriteableBitmap dest, Image sourceImg, double destX, double destY, Transform transform)
		{
			//consider: is this any better than simply calling bmp.Render  with translate xform? That seemed to work alright.
			dest.Invalidate();

			WriteableBitmap bmpImg = new WriteableBitmap((int)sourceImg.ActualWidth, (int)sourceImg.ActualHeight);
			bmpImg.Render(sourceImg, transform);
			bmpImg.Invalidate();
			FlipHorizontal(bmpImg);

			dest.Blit(
				new Rect(destX, destY, sourceImg.ActualWidth, sourceImg.ActualHeight),  //dest rect 
				bmpImg,  //to blit to the dest wbmp
				new Rect(0, 0, sourceImg.ActualWidth, sourceImg.ActualHeight)); //source

			dest.Invalidate();

			///imgTest.Source = bmpImg;
		}

		public void FlipHorizontal(WriteableBitmap wbmp)
		{
			//CANNOT get the scaletransform to render when the scale value's negative, so until that's sorted out
			//we'll do it by hand
			int width = wbmp.PixelWidth, height = wbmp.PixelHeight; //after examining the IL-cache the values so the CLR doesn't call them as much

			for (int y = 0; y < height; y++)
				for (int x = 0; x < width / 2; x++)
				{
					int lhsPixel = wbmp.Pixels[(y * width) + x];
					wbmp.Pixels[(y * width) + x] = wbmp.Pixels[(y * width) + (width - x-1)]; //assign the RHS pixel to the LHS pixel
					wbmp.Pixels[(y * width) + (width - x-1)] = lhsPixel;
				}
		}

		private void imgTest_ImageFailed(object sender, ExceptionRoutedEventArgs e)
		{

			Debug.WriteLine("failed");
		}

		BgRenderer bgLayer0 = null;
		WriteableBitmap wbmp = new WriteableBitmap(320, 240);
		Image img = new Image();
		private void btnRenderBG_Click(object sender, RoutedEventArgs e)
		{
			PrepForBGRenderTest();
		}

		private void PrepForBGRenderTest()
		{
			dt.Tick += (sender2, args) =>
			{
				if (Art.FinishedInitializing)
				{
					dt.Stop();
					LayoutRoot.Children.Clear();
					LayoutRoot.Children.Add(img);

					x = 160;
					bgLayer0.setCam(0, 0);
					//bgLayer0.render(wbmp, x, 0);

					btnRight.Visibility = btnLeft.Visibility = Visibility.Visible;					
				}
			};

			GraphicsConfiguration gc = new GraphicsConfiguration(LayoutRoot);
			Sonar.SonarSoundEngine engine = new Sonar.SonarSoundEngine();
			Art.init(gc, engine);

			bgLayer0 = new BgRenderer(BgLevelGenerator.createLevel(2048, 15, false, LevelGenerator.TYPE_OVERGROUND), gc, 320, 240, 2);
			img.Source = wbmp;
			LayoutRoot.Children.Add(img);


			dt.Start();
		}

		int x = 0;
		private void btnLeft_Click(object sender, RoutedEventArgs e)
		{
			MoveRight();
		}

		private void MoveRight()
		{
			if (x <= 0) return;
			x--;
			RenderBackground(x);
		}

		private void btnRight_Click(object sender, RoutedEventArgs e)
		{
			MoveRight();
		}

		private void MoveLeft()
		{
			if (x <= 0) return;
			x++;
			RenderBackground(x);
		}

		private void RenderBackground(int x)
		{
			bgLayer0.setCam(x, 0);
			bgLayer0.render(wbmp, x, 0);
			wbmp.Invalidate();
			img.Source = wbmp;
		}

		private void btnClear_Click(object sender, RoutedEventArgs e)
		{
			wbmp.Clear();
			img.Source = wbmp;
		}

        private void btnStartMario_Click(object sender, RoutedEventArgs e)
        {			
            StartMario();
			Focus();
        }


//end test



  
	}
}

